#include "napi/native_api.h"
#include "./common.h"
#include "./common.h"
#include "iostream"

#include <stdio.h>
#include <stdlib.h>
#include "threads.h"
#include <linux/sed-opal.h>
#include <unistd.h>
struct promiseInfo {
    napi_async_work worker;
    napi_deferred deferred;
    char *val;
};

struct promiseInfo data = { nullptr, nullptr, 0 };

void execute(napi_env env, void* data) {
    struct promiseInfo *arg = (struct promiseInfo *)data; 
    arg->val = "success";
}

void complete(napi_env env, napi_status status, void *data) {
    struct promiseInfo *arg = (struct promiseInfo *)data; 
    napi_value val; 
    if (true) { 
        // 执行 reslove 操作
        napi_create_string_utf8(env, arg->val, NAPI_AUTO_LENGTH, &val); 
        napi_resolve_deferred(env, arg->deferred, val);
    } else {
        // 执行 reject 操作
        napi_create_string_utf8(env, "error", NAPI_AUTO_LENGTH, &val);
        napi_reject_deferred(env, arg->deferred, val);
    }
    napi_delete_async_work(env, arg->worker); 
    arg->deferred = nullptr;
}

static napi_value getPromise(napi_env env, napi_callback_info info)
{
    size_t requireArgc = 2;
    size_t argc = 2;
    napi_value args[2] = {nullptr};
    NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args , nullptr, nullptr));
    
    napi_value promise;
    napi_value resourceName;
    
    struct promiseInfo *ptr = &data;
    NODE_API_CALL(env, napi_create_promise(env, &ptr->deferred, &promise));
    NODE_API_CALL(env, napi_create_string_utf8(env, "test", NAPI_AUTO_LENGTH, &resourceName));
    NODE_API_CALL(env, napi_create_async_work(env, nullptr, resourceName, execute, complete, ptr, &ptr->worker));
    napi_queue_async_work(env, ptr->worker);
    return promise;
}

auto successCb = [](napi_env env, napi_callback_info info) -> napi_value {
    size_t argc = 1;
    napi_value args[1] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    char v[20];
    size_t res;
    napi_get_value_string_utf8(env, args[0], v, 20, &res);
    return nullptr;
};

auto errorCb= [](napi_env env, napi_callback_info info) -> napi_value {
    size_t argc = 1;
    napi_value args[1] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    char v[20];
    size_t res;
    napi_get_value_string_utf8(env, args[0], v, 20, &res);
    return nullptr;
};

static napi_value handlePromise(napi_env env, napi_callback_info info) {
    size_t argsNum = 1;
    napi_value args[1] = { nullptr };
    napi_value context;
    napi_get_cb_info(env, info, &argsNum, args, &context, nullptr);
    napi_value promise;

    napi_call_function(env, context, args[0], 0, nullptr, &promise);
    
    napi_value promiseThen;
    napi_get_named_property(env, promise, "then", &promiseThen);
    
    napi_value promiseCatch;
    napi_get_named_property(env, promise, "catch", &promiseCatch);
    
    napi_value successFunc;
    napi_create_function(env, "successFunc", NAPI_AUTO_LENGTH, successCb, nullptr, &successFunc);
    
    napi_value errorFunc;
    napi_create_function(env, "errorFunc", NAPI_AUTO_LENGTH, errorCb, nullptr, &errorFunc);
    
    napi_value ret; 
    napi_call_function(env, promise, promiseThen, 1, &successFunc, &ret);
    napi_call_function(env, promise, promiseCatch, 1, &errorFunc, &ret);
    return context;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {
        { "getPromise", nullptr, getPromise, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "handlePromise", nullptr, handlePromise, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version =1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
    napi_module_register(&demoModule);
}
